﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;



namespace UtilityXml
{
    public class XmlForm
    {
        XmlDocument form;
        public string name{get; set;}

        
        public XmlForm(string formName)
        {
            name = formName;
            form = new XmlDocument();
            //XmlDeclaration xDecl = form.CreateXmlDeclaration(formName, , null);
            XmlElement xmlRootForm = form.CreateElement("", formName, "");
            form.AppendChild(xmlRootForm);            
        }

        
        //mod by v
        public void addWidget(Control c)
        {
            try
            {
                modifyWidget(c);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception modify node: " + e.Message);
                addNewWidget(c);
            }
            
        }

        //Add by v
        private void addNewWidget(Control c)
        {
            XmlNode root = form.SelectSingleNode(name);
            XmlNode newWidget = form.CreateNode(XmlNodeType.Element, "Widget", null);
            XmlAttribute attrName = form.CreateAttribute("Name");
            attrName.Value = c.Name;
            newWidget.Attributes.Append(attrName);
            try
            {
                XmlAttribute attrParent = form.CreateAttribute("Parent");
                attrParent.Value = c.Parent.Name;
                newWidget.Attributes.Append(attrParent);
            }
            catch (Exception)
            {
                
            }
            XmlAttribute attrType = form.CreateAttribute("Type");
            attrType.Value = c.GetType().ToString();
            newWidget.Attributes.Append(attrType);
            root.AppendChild(newWidget);

            addLocation(c, ref newWidget);
            addSize(c, ref newWidget);
            addAppearance(c, ref newWidget);
            addControloChildren(c, ref newWidget);
        }

        //add by v
        private void addLocation(Control c, ref XmlNode node) 
        {
            //position
            XmlNode location = form.CreateNode(XmlNodeType.Element, "Location", null);

            addChild(c.Location.X.ToString(), "X", ref location);
            addChild(c.Location.Y.ToString(), "Y", ref location);
            addChild(c.Dock.ToString(), "Dock", ref location);
            addChild(c.Anchor.ToString(), "Anchor", ref location);
         
            node.AppendChild(location);
        }

        //add by v
        private void addSize(Control c, ref XmlNode node)
        {
            XmlNode size = form.CreateNode(XmlNodeType.Element, "Size", null);

            addChild(c.Size.Width.ToString(), "Width", ref size);
            addChild(c.Size.Height.ToString(), "Height", ref size);

            node.AppendChild(size);
        }
        //add by v
        private void addAppearance(Control c, ref XmlNode node)
        {

            XmlNode appearance = form.CreateNode(XmlNodeType.Element, "Appearance", null);

            addChild(
                c.BackColor.R.ToString() + "," + c.BackColor.G.ToString() + "," + c.BackColor.B.ToString(),
                "BackColor",
                ref appearance
                );
            addChild(
                c.ForeColor.R.ToString() + "," + c.ForeColor.G.ToString() + "," + c.ForeColor.B.ToString(),
                "ForeColor",
                ref appearance
                );

            XmlNode font = form.CreateNode(XmlNodeType.Element, "Font", null);
            {
                addChild(c.Font.Name, "Name", ref font);
                addChild(c.Font.Size.ToString(), "Size", ref font);
                addChild(c.Font.Style.ToString(), "Style", ref font);
            }
            appearance.AppendChild(font);
            
            addChild(c.Text.ToString(), "Text", ref appearance);
            addChild(c.Cursor.ToString(), "Cursor", ref appearance);

            node.AppendChild(appearance);
        }
        //add by v
        private void addChild(String value, String element, ref XmlNode node)
        {
            XmlNode _node = form.CreateNode(XmlNodeType.Element, element, null);
            XmlAttribute _attr = form.CreateAttribute("Value");
            _attr.Value = value;
            _node.Attributes.Append(_attr);
            node.AppendChild(_node);
        }

        //add by v
        private Point LocationOnClient(Control c)
        {
            Point retval = new Point(0, 0);
            for (; c.Parent != null; c = c.Parent)
            { retval.Offset(c.Location); }
            return retval;
        }

        //add by v
        private void addControloChildren(Control c, ref XmlNode node)
        {
            //if (c.HasChildren)
            {
                XmlNode children = form.CreateNode(XmlNodeType.Element, "Children", null);
                XmlAttribute attrName = form.CreateAttribute("count");
                attrName.Value = c.Controls.Count.ToString();
                children.Attributes.Append(attrName);

                foreach (Control child in c.Controls)
                {
                    addChild(
                        child.Name,
                        "Child",
                        ref children
                        );
                }

                node.AppendChild(children);
            }
        }
        //mod by v
        public void modifyWidget(Control c) 
        {
            try
            {
                XmlNode temp = form.SelectSingleNode("/" + name + "/Widget[@Name='" + c.Name + "']");
                
                temp.RemoveChild(temp["Location"]);
                addLocation(c, ref temp);

                temp.RemoveChild(temp["Size"]);
                addSize(c, ref temp);

                temp.RemoveChild(temp["Appearance"]);
                addAppearance(c, ref temp);

                temp.RemoveChild(temp["Children"]);
                addControloChildren(c, ref temp);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void SaveXml(string path)
        {
            try
            {
                form.Save(path);
            }
            catch (Exception e) 
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
